package com.material.demo.record;

import android.media.AudioFormat;
import android.media.AudioManager;
import android.media.AudioTrack;
import android.os.Build;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;

/**
 * Created by WenJackp on 2017/2/20.
 */

public class AudioTrackHelper extends BaseRecordHelper {

    private static final String TAG = AudioTrackTask.class.getName();

    private AudioTrack track;

    private boolean mStopPlay;
    private boolean isPlaying;

    private int sampleRateInHz;
    private int channelConfig;
    private int audioFormat;
    private int minBufferSize;
    private int streamType;
    private int mode;

    private static AudioTrackHelper mHelper;

    public static AudioTrackHelper getInstance() {
        if (mHelper == null) {
            synchronized (AudioTrackHelper.class) {
                if (mHelper == null) {
                    mHelper = new AudioTrackHelper();
                }
            }
        }
        return mHelper;
    }

    public static AudioTrackHelper createNewHelper() {
        return new AudioTrackHelper();
    }

    AudioTrackHelper() {
        //初始化默认配置
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            channelConfig = AudioFormat.CHANNEL_IN_MONO;
        } else {
            channelConfig = AudioFormat.CHANNEL_CONFIGURATION_MONO;
        }

        sampleRateInHz = DEFAULT_SAMPLE_RATE;
        audioFormat = AudioFormat.ENCODING_PCM_16BIT;
        streamType = AudioManager.STREAM_MUSIC;
        mode = AudioTrack.MODE_STREAM;
    }

    public void play(File file) {

        sampleRateInHz = getBestSimpleRate(channelConfig, audioFormat, DEFAULT_SAMPLE_RATE, INVALID_VALUE);
        if (sampleRateInHz == INVALID_VALUE) {
            throw new RuntimeException("获取合适的采样率失败!");
        }

        minBufferSize = getMinBufferSize(sampleRateInHz, channelConfig, audioFormat, MIN_BUFFER_SIZE);

        if (track == null) {
            track = new AudioTrack(AudioManager.STREAM_MUSIC, sampleRateInHz, channelConfig, audioFormat, minBufferSize, mode);
        }

        isPlaying = true;
        mStopPlay = false;
        try {
            new Thread(new AudioTrackTask(new FileInputStream(file))).start();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
            isPlaying = false;
        }
    }

    public void play(InputStream stream) {

        sampleRateInHz = getBestSimpleRate(channelConfig, audioFormat, DEFAULT_SAMPLE_RATE, INVALID_VALUE);
        if (sampleRateInHz == INVALID_VALUE) {
            throw new RuntimeException("获取合适的采样率失败!");
        }

        minBufferSize = getMinBufferSize(sampleRateInHz, channelConfig, audioFormat, MIN_BUFFER_SIZE);

        if (track == null) {
            track = new AudioTrack(streamType, sampleRateInHz, channelConfig, audioFormat, minBufferSize, AudioTrack.MODE_STREAM);
        }

        isPlaying = true;
        mStopPlay = false;
    }

    public void pause() {

    }

    public void stop() {
        if (isPlaying) {
            isPlaying = false;
            mStopPlay = true;
            if (track != null) {
                track.stop();
            }
        }
    }

    public void release() {

    }

    class AudioTrackTask implements Runnable {

        private InputStream stream;

        public AudioTrackTask(InputStream stream) {
            this.stream = stream;
        }

        @Override
        public void run() {
            BufferedInputStream bis = null;
            try {
                if (track != null) {
                    bis = new BufferedInputStream(stream);
                    byte[] buffer = new byte[512];
                    int len;
                    track.play();
                    while (!mStopPlay && ((len = bis.read(buffer)) != -1)) {
                        track.write(buffer, 0, len);
                    }
                    track.stop();
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                if (bis != null) {
                    try {
                        bis.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }

                if (stream != null) {
                    try {
                        stream.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }

                isPlaying = false;
            }
        }
    }

    @Override
    protected String getTag() {
        return TAG;
    }
}
